home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Entertainment / crabs.c
Text File  |  1986-04-19  |  9KB  |  320 lines

  1. /* ----------------- crabs ----------------- 
  2.  *
  3.  * Implementation of the crabs game for the
  4.  * Macintosh, written in Aztec C.
  5.  * See Scientific American, Sep 1985, p18-23.
  6.  * 
  7.  * Author:   Fons Rademakers, Nikhef-h/CERN
  8.  * Version:  29-oct-1985
  9.  * Revision:
  10.  *
  11.  */
  12.  
  13. #asm
  14. main
  15.     dc.w  $6400        ;ctl-enable, need time and locked in mem.
  16.     dc.w  0          ;update as often as possible
  17.     dc.w  $0001        ;don't react on any specific event
  18.     dc.w  0            ;no menu
  19.  
  20.     dc.w  open_-main        ;open routine
  21.     dc.w  nop_-main        ;prime routine
  22.     dc.w  control_-main    ;control routine
  23.     dc.w  nop_-main        ;status routine
  24.     dc.w  close_-main     ;close routine
  25.  
  26. title_
  27.     dc.b  8
  28.     dc.b  "Crabs   "
  29.     ds    0              ;for alignment
  30.  
  31.     public   _Uend_,_Dorg_,_Cend_
  32.  
  33. save_
  34.     lea     main+(_Uend_-_Dorg_)+(_Cend_-main),a4    ;set up globals
  35.     move.l  a0,Pbp_                                    ;save pb pointer
  36.     move.l  a1,Dp_                                    ;save DCE pointer
  37.     rts
  38.  
  39. restore_
  40.     move.l  Pbp_,a0
  41.     rts
  42. #endasm
  43.  
  44. #define     _DRIVER
  45. #define  SMALL_MEM
  46. #include <quickdraw.h>
  47. #include <memory.h>
  48. #undef   SMALL_MEM
  49. #include <event.h>
  50. #include <pb.h>
  51. #include <desk.h>
  52.  
  53. #define NULL  (0L)
  54.  
  55. #define BASE1 512        /* Mac screen size in x direction */
  56. #define BASE2 342        /* Mac screen size in y direction */
  57.  
  58. #define MAXVEL 8         /* max velocity of the crabs */
  59. #define CRABS 10         /* # of crabs */
  60.  
  61. #define SP (*(struct storage **)Dp->dCtlStorage)
  62.  
  63. DCEPtr  Dp;
  64. ParmBlkPtr  Pbp;
  65.  
  66. Rect wind_rect = {0, 0, 0, 0};
  67.  
  68. struct storage {
  69.    BitMap  crabmap[4];                /* the 4 crab bitmaps */
  70.     GrafPtr crabport;                  /* the crabs grafport */
  71.     Pattern gray;                      /* backgr fill pattern */
  72.     short   crabspace[4][16];          /* space for the 4 crab bitmaps */
  73.     short   portspace[54];             /* space for the crabport */
  74.     short   xvel[CRABS], yvel[CRABS];  /* the crabs velocity */
  75.     short   newdest[CRABS][2], olddest[CRABS][2]; /* the crabs pos. */
  76.     short   olddir[CRABS];             /* the direction the crab was going 
  77. */
  78.     Boolean oldbackgr[CRABS];          /* flag to see if crab was on backgr 
  79. */
  80. };
  81.  
  82. open()
  83. {
  84.     register WindowPtr wp;
  85.     register struct DCE *dp;
  86.     register struct storage *sp;
  87.     extern char title[];
  88.     struct windowpeek {
  89.         GrafPort port;
  90.         int      windowKind;
  91.     };
  92.     short    x, i, dir;
  93.     Rect     destrect;
  94.  
  95.     save();
  96.     dp = Dp;
  97.     if (dp->dCtlWindow == NULL) {
  98.         HLock(dp->dCtlStorage = NewHandle((long) sizeof(struct storage)));
  99.         sp = SP;
  100.         /* create an invisible window */
  101.         dp->dCtlWindow =         
  102.         wp = NewWindow(NULL, &wind_rect, title, FALSE, plainDBox, -1L, FALSE, 
  103. NULL);
  104.         ((struct windowpeek *)wp)->windowKind = dp->dCtlRefNum;
  105.         /* allocate space for new crabport */
  106.         &sp->crabport->device = sp->portspace;
  107.         OpenPort(sp->crabport);
  108.         /* set the 4 crab bitmaps */
  109.         for(i = 0; i < 4; i++){
  110.             sp->crabmap[i].bounds.top    = 0;
  111.             sp->crabmap[i].bounds.left   = 0;
  112.             sp->crabmap[i].bounds.bottom = 8;
  113.             sp->crabmap[i].bounds.right  = 8;
  114.             sp->crabmap[i].rowBytes      = 2; /* needs to be even (to fit on a word) 
  115. */
  116.             sp->crabmap[i].baseAddr      = &sp->crabspace[i][0];
  117.         }
  118.         StuffHex(sp->crabmap[0].baseAddr, "\P910008007E004200810081004200BD00");
  119.         StuffHex(sp->crabmap[1].baseAddr, "\PBD0042008100810042007E0010008900");
  120.         StuffHex(sp->crabmap[2].baseAddr, "\PB1004C0084008500860084004C00B100");
  121.         StuffHex(sp->crabmap[3].baseAddr, "\P8D00320021006100A100210032008D00");
  122.         /* gray pattern */
  123.         StuffHex(sp->gray, "\PAA55AA55AA55AA55");
  124.         /* set the start positions of the crabs and draw them */
  125.         x   = 0;
  126.         dir = 1;
  127.         for (i = 0; i < CRABS; i++){
  128.             sp->newdest[i][0] = x;
  129.             sp->newdest[i][1] = 0;
  130.             x += BASE1/CRABS;
  131.  
  132.             destrect.left   = sp->newdest[i][0];
  133.             destrect.top    = sp->newdest[i][1];
  134.             destrect.right  = sp->newdest[i][0] + 8;
  135.             destrect.bottom = sp->newdest[i][1] + 8;
  136.             CopyBits(&sp->crabmap[dir], &sp->crabport->portBits,
  137.                      &sp->crabmap[dir].bounds, &destrect,
  138.                      srcCopy, NULL);
  139.             sp->olddir[i]     = dir;
  140.             sp->oldbackgr[i]  = FALSE;
  141.             sp->olddest[i][0] = sp->newdest[i][0];
  142.             sp->olddest[i][1] = sp->newdest[i][1];
  143.         }
  144.         /* set the background pattern to gray */
  145.         BackPat(sp->gray);
  146.  
  147.         HUnlock(dp->dCtlStorage);
  148.     }
  149.     restore();
  150.     return(0);
  151. }
  152.  
  153.  
  154. close()
  155. {
  156.     register struct DCE *dp;
  157.  
  158.     save();
  159.     dp = Dp;
  160.     /* get rid of the allocated space for the window and crabs */
  161.     DisposeWindow(dp->dCtlWindow);
  162.     dp->dCtlWindow = NULL;
  163.     DisposHandle(dp->dCtlStorage);
  164.     restore();
  165.     return(0);
  166. }
  167.  
  168.  
  169. nop()
  170. {
  171.     return(0);
  172. }
  173.  
  174.  
  175.  
  176.  
  177. control()
  178. {
  179.     register struct DCE *dp;
  180.     register struct storage *sp;
  181.     short   x, y, i, j, dir;
  182.     Rect    grayrect, destrect;
  183.     Boolean backgr;
  184.  
  185.     save();
  186.     dp = Dp;
  187.     HLock(dp->dCtlStorage);
  188.     sp = SP;
  189.     switch (Pbp->u.cp.csCode) {
  190.     case accRun:        /* time to move the crabs */
  191.         SetPort(sp->crabport);
  192.         for (i = 0; i < CRABS; i++) {
  193.             if (!sp->oldbackgr[i]) {
  194.                 /* if crab was not on bakcgr, determine complete
  195.                  * new x and y velocities */
  196.                 sp->xvel[i] = rand(-5, 5); 
  197.                 sp->yvel[i] = rand(-5, 5);
  198.             } else {
  199.                 /* if crab was on backgr, increase or decrease the
  200.                  * x and y velocities only slightly */
  201.                 if (sp->xvel[i] >= MAXVEL)
  202.                     sp->xvel[i] += rand(-1, 0);
  203.                 else if (sp->xvel[i] <= -MAXVEL)
  204.                     sp->xvel[i] += rand(0, 1);
  205.                 else 
  206.                     sp->xvel[i] += rand(-1,1);
  207.  
  208.                 if (sp->yvel[i] >= MAXVEL)
  209.                     sp->yvel[i] += rand(-1, 0);
  210.                 else if (sp->yvel[i] <= -MAXVEL)
  211.                     sp->yvel[i] += rand(0, 1);
  212.                 else
  213.                     sp->yvel[i] += rand(-1 ,1);
  214.             }
  215.             /* update the crab position */
  216.             sp->newdest[i][0] += sp->xvel[i];
  217.             sp->newdest[i][1] += sp->yvel[i];
  218.             /* make sure to remain within screen boundaries */
  219.             while ((sp->newdest[i][0] < 0) || (sp->newdest[i][0] > BASE1 - 8) ||
  220.                    (sp->newdest[i][1] < 0) || (sp->newdest[i][1] > BASE2 - 8)) {
  221.                 sp->newdest[i][0] -= sp->xvel[i];
  222.                 sp->newdest[i][1] -= sp->yvel[i];
  223.                 sp->xvel[i] = rand(-5, 5);
  224.                 sp->yvel[i] = rand(-5, 5);
  225.                 sp->newdest[i][0] += sp->xvel[i];
  226.                 sp->newdest[i][1] += sp->yvel[i];
  227.                }
  228.             /* calculate new direction of crab */
  229.             if (abs(sp->yvel[i]) >= abs(sp->xvel[i]))
  230.                 if (sp->yvel[i] <= 0) 
  231.                     dir = 0;
  232.                 else
  233.                     dir = 1;
  234.             else
  235.                 if (sp->xvel[i] >= 0)
  236.                     dir = 2;
  237.                 else
  238.                     dir = 3;
  239.             /* erase the crab from the previous position, by drawing
  240.              * it over with the gray background */
  241.             grayrect.left   = sp->olddest[i][0];
  242.             grayrect.top    = sp->olddest[i][1];
  243.             grayrect.right  = sp->olddest[i][0] + 8;
  244.             grayrect.bottom = sp->olddest[i][1] + 8;
  245.             EraseRect(&grayrect);
  246.  
  247.             /* determine if the new position does occupy a
  248.              * non gray site */
  249.             j = 0;
  250.             backgr = TRUE;
  251.             x = sp->newdest[i][0];
  252.             if (sp->xvel[i] > 0)   
  253.                 y = sp->newdest[i][1] + 7;  /* scan only bottom line */
  254.             else                            /* of new crab position  */
  255.                 y = sp->newdest[i][1];      /* or only top line      */
  256.             for (;x <= sp->newdest[i][0] + 7; x++) 
  257.                 if (GetPixel(x, y)) j++;
  258.             if (j != 4) backgr = FALSE;
  259.             sp->oldbackgr[i] = backgr;
  260.  
  261.             if (!backgr) {
  262.                 /* if the site is not gray, make it gray and redraw
  263.                     * the crab in the previous position */
  264.                 grayrect.left   = sp->newdest[i][0];
  265.                 grayrect.top    = sp->newdest[i][1];
  266.                 grayrect.right  = sp->newdest[i][0] + 8;
  267.                 grayrect.bottom = sp->newdest[i][1] + 8;
  268.                 EraseRect(&grayrect);
  269.                 destrect.left   = sp->olddest[i][0];
  270.                 destrect.top    = sp->olddest[i][1];
  271.                 destrect.right  = sp->olddest[i][0] + 8;
  272.                 destrect.bottom = sp->olddest[i][1] + 8;
  273.                 dir             = sp->olddir[i];
  274.                 CopyBits(&sp->crabmap[dir], &sp->crabport->portBits, 
  275.                          &sp->crabmap[dir].bounds, &destrect,
  276.                          srcCopy, NULL);
  277.                 sp->newdest[i][0] = sp->olddest[i][0];
  278.                 sp->newdest[i][1] = sp->olddest[i][1];
  279.             } else {
  280.                 /* if the site is gray, draw the crab in the new
  281.                  * position */
  282.                 destrect.left   = sp->newdest[i][0];
  283.                 destrect.top    = sp->newdest[i][1];
  284.                 destrect.right  = sp->newdest[i][0] + 8;
  285.                 destrect.bottom = sp->newdest[i][1] + 8;
  286.                 CopyBits(&sp->crabmap[dir], &sp->crabport->portBits,
  287.                          &sp->crabmap[dir].bounds, &destrect,
  288.                          srcCopy, NULL);
  289.                 sp->olddest[i][0] = sp->newdest[i][0];
  290.                 sp->olddest[i][1] = sp->newdest[i][1];
  291.                 sp->olddir[i]     = dir;
  292.             }
  293.         }
  294.         break;  /* end case */
  295.     }
  296.     HUnlock(dp->dCtlStorage);
  297.     restore();
  298.     return(0);
  299. }
  300.  
  301.  
  302. /* Return random number uniformly distributed on [min,max].
  303.  * Note that Random() delivers a value on [-32768,32767]. */
  304. rand(min, max)
  305. int min, max;
  306. {
  307.     float ran;
  308.  
  309.     ran = (max - min + 1.0)*(float)abs(Random())/32768.0 + min;
  310.     return((ran < 0) ? --ran : ran);
  311. }
  312.  
  313.  
  314. /* Return absolute value of an integer */
  315. abs(n)
  316. int n;
  317. {
  318.     return((n > 0) ? n : -n);
  319. }
  320.